<template>
  <div class="introduction">
    <canvas
      width="400"
      height="300"
      style="background: #1cc09f"
      id="Canvas"
      ref="Canvas"
      @click="ctxclick"
      @contextmenu="contextmenu"
      @mousedown="ctxMouseDown"
      @mouseup="ctxMouseUp"
      @mousemove="ctxMouseMove">
    </canvas>
  </div>
</template>

<script>
export default {
  name: 'Collection',
  data () {
    return {
      outCoords: [],
      outPoints: 10,
      dragIndex: 0,
      isDragOut: false,
      isDrawOut: false,
      startPoint: {},
      areaList: [],
      activeIndex: -1
    }
  },
  methods: {
    // 点击canvas区域添加小方块，与上一次方块进行连线
    ctxclick (e) {
      let coord = this.getPosition(e)
      if (this.outCoords.length < this.outPoints && this.isDrawOut) {
        this.drawDot(coord)
        this.outCoords.push(coord)
      }
      if (this.outCoords.length === this.outPoints) {
        this.contextmenu()
      }
    },
    contextmenu (e) {
      console.log(12331)
      e && e.preventDefault()
      this.isDrawOut = false
      this.isDragOut = false
      if (this.outCoords.length > 2) {
        this.areaList.push([...this.outCoords])
      }
      this.ctx.clearRect(0, 0, 400, 300)
      this.drawAreaList()
      this.outCoords = []
      return false
    },
    ctxMouseMove (e) {
      let coord = this.getPosition(e)
      if (this.outCoords.length && this.outCoords.length !== this.outPoints && this.isDrawOut) {
        this.ctx.clearRect(0, 0, 400, 300)
        this.drawingOut(coord)
        this.drawAreaList()
      }
      if (this.isDragOut) {
        this.ctx.clearRect(0, 0, 400, 300)
        this.dragingOut(coord)
        this.drawAreaList()
      }
    },
    ctxMouseDown (e) {
      let coord = this.getPosition(e)
      // 鼠标落下判断所在区域
      this.activeIndex = -1
      if (!this.isDrawOut && !this.isDragOut && this.areaList.length) {
        this.areaList.forEach((item, i) => {
          if (this.rayCasting(coord, this.areaList[i]) === 'in') {
            this.activeIndex = i
          }
        })
        this.ctx.clearRect(0, 0, 400, 300)
        this.drawAreaList()
      }
    },
    ctxMouseUp (e) {
      if (this.outCoords.length === this.outPoints) {
        this.contextmenu()
      }
    },
    // 绘制时移动
    drawingOut (coord) {
      let tmpCoords = [...this.outCoords, coord]
      tmpCoords.forEach((item, index) => {
        if (index === 0) {
          this.ctx.beginPath()
          this.ctx.moveTo(this.outCoords[0].x, this.outCoords[0].y)
        } else if (index === (tmpCoords.length - 1)) {
          this.ctx.lineTo(tmpCoords[index].x, tmpCoords[index].y)
          this.ctx.closePath()
        } else {
          this.ctx.lineTo(tmpCoords[index].x, tmpCoords[index].y)
        }
      })
      this.ctx.strokeStyle = '#000'
      this.ctx.stroke()
      tmpCoords.forEach((item, index) => {
        this.drawDot(item)
      })
    },
    // 已绘制好外框图形移动
    dragingOut (coord) {
      this.outCoords[this.dragIndex] = coord
      this.drawOutLine()
      this.drawOutDot()
    },
    // 获取坐标点
    getPosition (e) {
      let [x, y] = [e.offsetX, e.offsetY]
      return {
        x: x,
        y: y
      }
    },
    // 绘制每个角小方块
    drawDot (e) {
      // 小方块1/2边长
      let l = 2
      this.ctx.fillStyle = '#e4393c'
      this.ctx.fillRect(e.x - l, e.y - l, l * 2, l * 2)
    },
    // 绘制外框线条
    drawOutLine (coords, bool) {
      coords = coords || this.outCoords
      coords.forEach((item, index) => {
        if (index === 0) {
          this.ctx.beginPath()
          this.ctx.moveTo(coords[0].x, coords[0].y)
        } else if (index === (coords.length - 1)) {
          this.ctx.lineTo(item.x, item.y)
          this.ctx.closePath()
        } else {
          this.ctx.lineTo(item.x, item.y)
        }
      })
      this.ctx.strokeStyle = bool ? '#f00' : '#000'
      this.ctx.stroke()
    },
    // 绘制外框小方格
    drawOutDot () {
      this.outCoords.forEach((item, index) => {
        this.drawDot(item)
      })
    },
    // 绘制已完成的区域
    drawAreaList () {
      this.areaList.forEach((item, i) => {
        this.drawOutLine(item, i === this.activeIndex)
      })
    },
    startDraw () {
      this.isDrawOut = true
      this.activeIndex = -1
    },
    clearDraw () {
      this.ctx.clearRect(0, 0, 400, 300)
      this.outCoords = []
      this.areaList = []
      this.isDrawOut = false
      this.isDragOut = false
      this.activeIndex = -1
    },
    clearActive () {
      if (this.activeIndex !== -1) {
        this.areaList.splice(this.activeIndex, 1)
        this.activeIndex = -1
        this.ctx.clearRect(0, 0, 400, 300)
        this.drawAreaList()
      }
    },
    rayCasting (p, poly) {
      var px = p.x,
        py = p.y,
        flag = false

      for (var i = 0, l = poly.length, j = l - 1; i < l; j = i, i++) {
        var sx = poly[i].x,
          sy = poly[i].y,
          tx = poly[j].x,
          ty = poly[j].y

        // 点与多边形顶点重合
        if ((sx === px && sy === py) || (tx === px && ty === py)) {
          return 'on'
        }

        // 判断线段两端点是否在射线两侧
        if ((sy < py && ty >= py) || (sy >= py && ty < py)) {
          // 线段上与射线 Y 坐标相同的点的 X 坐标
          var x = sx + (py - sy) * (tx - sx) / (ty - sy)

          // 点在多边形的边上
          if (x === px) {
            return 'on'
          }

          // 射线穿过多边形的边界
          if (x > px) {
            flag = !flag
          }
        }
      }

      // 射线穿过多边形边界的次数为奇数时点在多边形内
      return flag ? 'in' : 'out'
    }
  },
  mounted () {
    this.ctx = this.$refs.Canvas.getContext('2d')
    document.oncontextmenu = (e) => {
      this.contextmenu(e)
      return false
    }
  },
  beforeDestroy () {
    document.oncontextmenu = null
  }
}
</script>

<style scoped>
</style>
